-- BuffDataM
-- Create by chendh
-- buff_data模块

module("BuffDataM", package.seeall);

local buffDataConfig = {}

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    local buff_data_CSV = get_buff_data_CSV();
    buffDataConfig = {};

    for i=1, #buff_data_CSV do
        buffDataConfig[buff_data_CSV[i].key] = buff_data_CSV[i];
    end

    buff_data_CSV = {};
end

-- 模块初始化
function init()
    loadCsv();
end

-- 设置数据
function setBuffData(attrib, buf)
    -- 将buff_data数据类型转化为table
    local buffer = Buffer.create(buf);
    local tableData = {};
    local tempData = {};
    local offset = 1;
    local size = Buffer.size(buffer);
    local cfg = buffDataConfig[attrib];

    if not cfg then
        print("要查询的属性" .. attrib .. "不是buff_data。");
        return;
    end

    -- 将buffer按位转化为table
    while (offset <= size) do
        local amount = Buffer.getu8(buffer, offset);

        local len = 8;
        local index = len;
        while index >= 1 do
            local num = math.pow(2, index - 1);
            if amount >= num then
                tempData[(offset - 1) * len + len - index + 1] = 1;
                amount = amount - num;
            end

            index = index - 1;
        end

        -- 继续下一个道具
        offset = offset + 1;
    end

    -- 根据配置表的规则，将连续N位的bit组成一个单元的数据
    local index = 1;
    while (index - 1) * cfg.plot_size < size * 8 do
        local num = 0;
        for i = 1, cfg.plot_size do
            num = num * 2 + (tempData[(index - 1) * cfg.plot_size + i] or 0);
        end

        tableData[index] = num;
        index = index + 1;
    end

    ME.user.dbase:set(attrib, tableData);
end

-- 查询进度
function query(attrib, id)
    local cfg = buffDataConfig[attrib];

    if not cfg then
        print("要查询的属性" .. attrib .. "不是buff_data。");
        do return 0; end
    end

    local data = ME.user.dbase:query(attrib) or {};

    if id == nil then
        return data;
    end

    if id <= 0 then
        print("越界访问。");
        return 0;
    end

    return data[id] or 0;
end

-- 根据数据查询进度
function queryByData(buf, id, oneSize)
    if id == nil then
        return buf;
    end

    if id <= 0 then
        print("越界访问。");
        return 0;
    end

    local data = parseBufferData(buf, oneSize);

    return data[id] or 0;
end

-- 设置单元数据
function set(attrib, id, value)
    local cfg = buffDataConfig[attrib];

    if not cfg then
        print("要查询的属性" .. attrib .. "不是buff_data。");
        do return 0; end
    end

    if id <= 0 then
        print("越界访问。");
        return 0;
    end

    local data = ME.user.dbase:query(attrib) or {};

    if value > cfg.imax then
        value = cfg.imax;
    end
    data[id] = value;

    ME.user.dbase:set(attrib, data);
end

-- 获取所有的buff data配置
function getBuffDataCfg()
    return buffDataConfig;
end

-- 打包buffdata
function packBuffData()
    -- TODO: buff_data收集
    local cfg = BuffDataM.getBuffDataCfg();
    local buffData = {__mapping=1};
    for attrib, _ in pairs(cfg) do
        -- 有变动的buff_data才需要同步
        local value = ME.user.dbase:query(attrib);
        if value then
            -- 从dbase中删除
            dbase[attrib] = nil;

            -- 另外记录下来
            buffData[attrib] = value;
        end
    end
end

-- 解析buffer数据
function parseBufferData(buf, oneSize)
    -- 将buff_data数据类型转化为table
    local buffer = Buffer.create(buf);
    local tableData = {};
    local tempData = {};
    local offset = 1;
    local size = Buffer.size(buffer);

    -- 将buffer按位转化为table
    while (offset <= size) do
        local amount = Buffer.getu8(buffer, offset);

        local len = 8;
        local index = len;
        while index >= 1 do
            local num = math.pow(2, index - 1);
            if amount >= num then
                tempData[(offset - 1) * len + len - index + 1] = 1;
                amount = amount - num;
            end

            index = index - 1;
        end

        -- 继续下一个道具
        offset = offset + 1;
    end

    -- 根据配置表的规则，将连续N位的bit组成一个单元的数据
    local index = 1;
    while (index - 1) * oneSize < size * 8 do
        local num = 0;
        for i = 1, oneSize do
            num = num * 2 + (tempData[(index - 1) * oneSize + i] or 0);
        end

        tableData[index] = num;
        index = index + 1;
    end

    return tableData;
end